#pragma once

#include "SimplygonAssetUserData.h"
#include "SimplygonUE4UI.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "SimplygonBlueprintLibrary.generated.h"

class AActor;
class AStandInMeshActor;
class ULODRecipe;

/**
* Simplygon Blueprint Function library that exposes essential methods for automating content pipeline through python scripting.
*/
UCLASS(MinimalAPI, meta = (ScriptName = "SimplygonBlueprintLibrary"))
class USimplygonBPFunctionLibrary : public UBlueprintFunctionLibrary
{
	GENERATED_UCLASS_BODY()

public:

	/**
	* Builds meshes for all standin actors
	* @return True if successful.
	*/
	UFUNCTION(BlueprintCallable, Category = "Standin")
	static bool BuildStandinMeshes();

	/**
	* Create standin actor from a given list of static mesh actors.
	* @param InActors list of static mesh actors.
	* @return the newly created standin mesh actor
	*/
	UFUNCTION(BlueprintCallable, Category = "Standin")
	static AStandInMeshActor* CreateStandinActorFromActors( const TArray<AActor*>& InActors );
	
	/**
	* Adds a static mesh actor to standin actor.
	* @param InStandin the standin actor.
	* @param InActor static mesh actor to add.
	*/
	UFUNCTION(BlueprintCallable, Category = "Standin")
	static void AddActorToStandinActor(AStandInMeshActor* InStandin, AActor* InActor);

	/**
	 * Adds a list of static mesh actors to standin actor.
	 * @param InStandin The stand in actor.
	 * @param InActors list of static mesh actors to add.
	 */
	UFUNCTION(BlueprintCallable, Category = "Standin")
	static void AddActorsToStandinActor(AStandInMeshActor* InStandin,const TArray<AActor*>& InActors);

	/**
	 * Remove given static mesh actor from a standin actor.
	 * @param InActor The stand in actor.
	 */
	UFUNCTION(BlueprintCallable, Category = "Standin")
	static void RemoveActorFromStandinActor(AActor* InActor);

	/**
	* Remove given list of static mesh actros from standin actor.
	* @oaram InStandin standin actor
	* @param InActors list of static mesh actors.
	*/
	UFUNCTION(BlueprintCallable, Category = "Standin")
	static void RemoveActorsFromStandinActor(AStandInMeshActor* InStandin, const TArray<AActor*>& InActors);

	/**
	* Build all LODRecipes
	*/
	UFUNCTION( BlueprintCallable, Category = "LODRecipe" )
	static void BuildAllLODRecipes();

	/**
	* Build LODRecipe for given static/skeletal mesh.
	* @param Mesh static/skeletal mesh actor. 
	*/
	UFUNCTION( BlueprintCallable, Category = "LODRecipe" )
	static void BuildLODRecipe( TSoftObjectPtr<UObject> Mesh );

	/**
	* Build given list of LODRecipes. Only for static mesh actors.
	* @param LODRecipes list of LODRecipes to build.
	*/
	UFUNCTION( BlueprintCallable, Category = "LODRecipe" )
	static void BuildLODRecipesOnlyForStaticMeshes( const TArray<ULODRecipe*>& LODRecipes);

	/**
	 * Build given list of LODRecipes. Only for skeletal mesh actors.
	 * @param LODRecipes list of LODRecipes to build.
	 */
	UFUNCTION( BlueprintCallable, Category = "LODRecipe" )
	static void BuildLODRecipesOnlyForSkeletalMeshes( const TArray<ULODRecipe*>& LODRecipes );


	/**
	 * Assign given LODRecipe to given static/skeletal mesh actor
	 * @param InRecipe LODRecipes to assign.
	 * @param InAsset static/skeletal mesh asset.
	 */
	UFUNCTION( BlueprintCallable, Category = "LODRecipe" )
	static void AssignRecipeToAsset( ULODRecipe* InRecipe, UObject* InAsset );

	/**
	 * Check if clipping geometry tag is associated with static mesh actor.
	 * @param InActor static mesh actor to look for the tag.
	 * @return True if clipping geometry tag is associated with static mesh actor.
	 */
	UFUNCTION( BlueprintCallable, Category = "SimplygonUtils" )
	static bool IsClippingGeometry( AActor* InActor );

	/**
	 * Check if occluding geometry tag is associated with static mesh actor.
	 * @param InActor static mesh actor to look for the tag.
	 * @return True if occluding geometry tag is associated with static mesh actor.
	 */
	UFUNCTION( BlueprintCallable, Category = "SimplygonUtils" )
	static bool IsOccludingGeometry( AActor* InActor );

	/**
	 * Adds Simplygon user data to static mesh actor. 
	 * @param InActor static mesh actor to assign user data to.
	 * @param InMetaTag meta tag to assign to static mesh actor.
	 */
	UFUNCTION( BlueprintCallable, Category = "SimplygonUtils" )
	static void AddSimplygonUserData( AActor* InActor, ESimplygonMetaTagType InMetaTag );

	/**
	 * Removes Simplygon user data from actor.
	 * @param InActor static mesh actor to remove user data from.
	 */
	UFUNCTION( BlueprintCallable, Category = "SimplygonUtils" )
	static void RemoveSimplygonUserData( AActor* InActor );
	
	/**
	 * Set LODRecipe allow morph target setting
	 */
	UFUNCTION(BlueprintCallable, Category = "SimplygonUtils")
	static void SetLODRecipeAllowMorphTargets(ULODRecipe* Recipe, bool bAllowMorphLOD1, bool bAllowMorphLOD2, bool bAllowMorphLOD3, bool bAllowMorphLOD4);
	
	/**
	 * Set LODRecipe reduction settings
	 */
	UFUNCTION(BlueprintCallable, Category = "SimplygonUtils")
	static void SetLODRecipeReductionSetting(ULODRecipe* Recipe, int NumLODs, bool bSetReductionLOD1, bool bSetReductionLOD2, bool bSetReductionLOD3, bool bSetReductionLOD4, FReductionSettings LOD1Settings, FReductionSettings LOD2Settings, FReductionSettings LOD3Settings, FReductionSettings LOD4Settings);
};